use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::response::Json;
use axum::response::Response;
use serde::Deserialize;
use serde::Serialize;
use thiserror::Error;
use utoipa::ToSchema;

#[derive(Debug, ToSchema, Serialize, Deserialize)]
pub struct ErrorOutput {
    pub error: String,
}

#[derive(Error, Debug)]
pub enum AppError {
    #[error("chat not found: {0}")]
    ChatNotFound(String),

    #[error("file not found: {0}")]
    FileNotFound(String),

    #[error("invalid chat members: {0}")]
    CreateChatError(String),

    #[error("email already exists: {0}")]
    EmailAlreadyExists(String),

    #[error("sqlx error: {0}")]
    SqlxError(#[from] sqlx::Error),

    #[error("not found")]
    NotFound,
    #[error("internal server error")]
    InternalServerError,

    #[error("password hash error:{0}")]
    PasswordHasError(#[from] argon2::password_hash::Error),

    #[error("jwt error: {0}")]
    JwtError(#[from] jwt_simple::Error),

    #[error("http header error: {0}")]
    HttpHeaderError(#[from] axum::http::header::ToStrError),
    #[error("no permission")]
    NoPermission,

    #[error("io  error: {0}")]
    IoError(#[from] std::io::Error),

    #[error("internal server error: {0}")]
    CreateMessagesError(String),
    #[error("chat file  error: {0}")]
    ChtFileError(String),

    #[error("page size error: {0}")]
    PageSizeError(String),
    #[error("page index error: {0}")]
    PageIndexError(String),
}

impl ErrorOutput {
    pub fn new(error: impl Into<String>) -> Self {
        Self {
            error: error.into(),
        }
    }
}
impl IntoResponse for AppError {
    fn into_response(self) -> Response<axum::body::Body> {
        let status = match &self {
            Self::SqlxError(_) => StatusCode::INTERNAL_SERVER_ERROR,
            Self::NotFound => StatusCode::NOT_FOUND,
            Self::InternalServerError => StatusCode::INTERNAL_SERVER_ERROR,
            Self::PasswordHasError(_) => StatusCode::UNPROCESSABLE_ENTITY,
            Self::JwtError(_) => StatusCode::FORBIDDEN,
            Self::HttpHeaderError(_) => StatusCode::UNPROCESSABLE_ENTITY,
            Self::EmailAlreadyExists(_) => StatusCode::CONFLICT,
            Self::CreateChatError(_) => StatusCode::BAD_REQUEST,
            Self::ChatNotFound(_) => StatusCode::NOT_FOUND,
            Self::NoPermission => StatusCode::FORBIDDEN,
            Self::IoError(_) => StatusCode::INTERNAL_SERVER_ERROR,
            Self::FileNotFound(_) => StatusCode::NOT_FOUND,
            Self::CreateMessagesError(_) => StatusCode::BAD_REQUEST,
            Self::ChtFileError(_) => StatusCode::NOT_FOUND,
            Self::PageSizeError(_) => StatusCode::BAD_REQUEST,
            Self::PageIndexError(_) => StatusCode::BAD_REQUEST,
        };
        (status, Json(ErrorOutput::new(self.to_string()))).into_response()
    }
}
